package com.xunsiya.common.config;

import com.xunsiya.tools.common.string.StringUtil;
import com.xunsiya.tools.file.xml.XMLParser;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 配置文件管理. <br/>
 * 自动从config.XXX的文件夹中获得xxxx.config.xml文件作为配置的读取文件， 其中配置的格式为
 * 
 * <configs><config name="" value=""/></configs>,其中name表示配置的名称，value表示配置对应的值
 * 
 * @date 2013-12-17
 * @author zhangxw
 */
public class PropertyConfig {

    private static Logger log = Logger.getLogger(PropertyConfig.class);

    /**
     * 是否已经初始化过
     */
    private static boolean inited = false;

    /**
     * 初始化锁
     */
    private static final Object LOCK = new Object();

    /**
     * 配置的参数列表
     */
    private static Map<String, String> configMap = new HashMap<>(128);

    static void init() throws Exception{
        if (inited) {
            return;
        }
        synchronized (LOCK) {
            if (inited) {
                return;
            }
            String locationPatternT = null;
            if(StringUtil.isEmpty(locationPatternT)){
                locationPatternT = "classpath*:config/**/*.config.xml";
            }
            Resource[] resArr = new PathMatchingResourcePatternResolver().getResources(locationPatternT);
            if (resArr.length > 0) {
                for (Resource res : resArr) {
                    readResource(res);
                }
            }
            inited = true;
        }

    }

    /**
     * 读取资源文件,并且写入到配置参数列表中
     * 
     * @param res
     *            资源文件
     */
    @SuppressWarnings("unchecked")
    private static void readResource(Resource res) throws Exception{
        Document doc = XMLParser.createXMLParser(res.getInputStream(),
                "utf-8");
        List<Element> configElementList = doc.selectNodes("//config");
        if (null != configElementList) {
            for (Element configEle : configElementList) {
                String[] nameValue = parseNameValue(configEle);
                configMap.put(nameValue[0], nameValue[1]);
            }
        }
    }

    /**
     * 解析元素的name属性值和value属性值
     * 
     * @param configEle
     *            要解析的元素
     * @return name属性值和value属性值
     */
    private static String[] parseNameValue(Element configEle) {
        String name = configEle.attributeValue("name");
        String value = configEle.attributeValue("value");
        return new String[] { name, value };
    }

    /**
     * 根据配置的名称name查找对应的值
     * 
     * @param name
     *            配置的名称
     * @return 对应的值
     */
    public static String getProperty(String name) {
        try {
            init();
        }catch (Exception e) {
            log.error("init error", e);
        }
        return configMap.get(name);
    }

    
    /**
     * 通过指定的java类和属性的名称，查找到的值并且转换为相应的分类
     * @param <T>
     * @param name 属性的名称
     * @param tc java类
     * @return java类的对象
     */
    @SuppressWarnings("unchecked")
    static <T> T getObjectProperty(String name,Class<T> tc){
        String value = getProperty(name);
        if (StringUtil.isEmpty(value)) {
            return null;
        }
        try {
            Method m = tc.getDeclaredMethod("valueOf", String.class);
            return (T) m.invoke(null, value);
        } catch (Exception e) {
            log.error("",e);
        }
        return null;
    }
    
    /**
     * 获得boolean型数据
     * @param name  属性的名称
     * @return  boolean型数据
     */
	public static Boolean getBooleanProperty(String name) {
		Boolean f = getObjectProperty(name, Boolean.class);
		if(f == null){
			f = false;
		}
		return f;
	}
    /**
     * 获得长整形数据
     * @param name  属性的名称
     * @return  长整形数据
     */
    public static Long getLongProperty(String name) {
        return getObjectProperty(name, Long.class);
    }
    
    /**
     * 获得整形数据
     * @param name  属性的名称
     * @return  整形数据
     */
    public static Integer getIntegerProperty(String name) {
        return getObjectProperty(name, Integer.class);
    }
    /**
     * 获得整形数据
     * @param name  属性的名称
     * @param defaultVal 属性默认值
     * @return  整形数据
     */
    public static Integer getIntegerProperty(String name, Integer defaultVal) {
        Integer value = getObjectProperty(name, Integer.class);
        if(value==null){
            return defaultVal;
        }
        return value;
    }
    
    /**
     * 获得浮点数据
     * @param name  属性的名称
     * @return  浮点数据
     */
    public static Float getFloatProperty(String name) {
        return getObjectProperty(name, Float.class);
    }
    /**
     * 获得浮点数据
     * @param name  属性的名称
     * @param defaultVal 属性默认值
     * @return  浮点数据
     */
    public static Float getFloatProperty(String name, Float defaultVal) {
        Float value = getObjectProperty(name, Float.class);
        if(value==null){
            return defaultVal;
        }
        return value;
    }
    
    /**
     * 获得双精度数据
     * @param name  属性的名称
     * @return  双精度数据
     */
    public static Double getDoubleProperty(String name) {
        return getObjectProperty(name, Double.class);
    }
    
    /**
     * 获得双精度数据
     * @param name  属性的名称
     * @param defaultValue 属性默认值
     * @return  双精度数据
     */
    public static Double getDoubleProperty(String name, Double defaultValue) {
        Double d = getObjectProperty(name, Double.class);
        if(d==null){
            return defaultValue;
        }
        return d;
    }
}
